#ifndef PROCESSORS_GENERATOR_HPP_
#define PROCESSORS_GENERATOR_HPP_

/**
 * @file processors_generator.hpp
 * @brief randomly generate connected processors
 * @author Hu Qian
 * @date 2014-10.30
 * @version 0.1 create
 */

#include <map>

/*
Examples:

1.
	using namespace processors;
	RandomGenerator<ComputeRandom100Generator, ComputeRandom100Generator> prg;
	prg.printProcessors( prg.Generate(5) );


*/

namespace processors{

	// randomly generate integer from 0 to 99
	class ComputeRandom100Generator{
	public:
		int generate() const{
			return rand() % 100;
		};
	};

	// generate a const integer
	template <int N = 1>
	class ComputeConstGenerator
	{
	public:
		int generate() const{
			return N;
		}
	};

	/************************************************************************/
	/*    class Generator                                                   */
	/*            the class generates connected processors					*/
	/************************************************************************/

	template <typename PROCESSOR_COMPUTATION_COST_GENERATOR = ComputeRandom100Generator, 
			  typename COMMUNICATION_COST_GENERATOR = ComputeConstGenerator<> >
	class RandomGenerator{

	public:
		struct Processors{
			std::map< int, int >					computation_cost;
			std::map< int, std::map<int,int> >		communicaiton_cost;
		};

	protected:
		
		// task computation cost (random) generator
		const PROCESSOR_COMPUTATION_COST_GENERATOR	task_computation_cost_generator_;

		// communication cost (random) generator
		const COMMUNICATION_COST_GENERATOR communication_cost_generator_;

	public:
		
		// constructor
		RandomGenerator(){
			// nothing to do
		};

		// destructor
		virtual ~RandomGenerator(){
			// nothing to do
		};

		//************************************
		// Method:    Generate
		// FullName:  dag::RandomGenerator<TASK_COMPUTATION_COST_GENERATOR, COMMUNICATION_COST_GENERATOR>::Generate
		// Access:    public 
		// Returns:   DirectedGraph
		// Qualifier: const
		// Parameter: int node_number - total node number including one source and one sink
		//************************************
		Processors Generate( int processor_number ) const {
			Processors procs;

			std::map<int,int> dummy;
			for(int i=0; i<processor_number;i++){
				procs.computation_cost[i] = task_computation_cost_generator_.generate();

				procs.communicaiton_cost[i] = dummy;
			}

			for(int i=0; i<processor_number; i++){
				for(int j=i; j<processor_number; j++){

					if (i==j){
						procs.communicaiton_cost[i][j] = 0;
					}else{
						procs.communicaiton_cost[i][j] = procs.communicaiton_cost[j][i] = 
							communication_cost_generator_.generate();
					}
				}
			}

			return procs;
		}

		// for debug - print out all processors
		void printProcessors( Processors& procs ) const
		{
			cout << "---------- begin print processors ----------" << endl;

			for(size_t i=0; i<procs.computation_cost.size(); ++i){
				cout << "Processor " << i <<" (" << procs.computation_cost[i] << ") : ";

				for(size_t j=0; j<procs.computation_cost.size(); ++j){
					cout << procs.communicaiton_cost[i][j] << "\t";
				}

				cout << endl;
			}
			

			cout << "---------- end print processors ----------" << endl;
		};

	};

};

#endif
